﻿using System;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Xrm.Sdk;
using CrmClient.Mapping;
using System.Collections.Generic;

namespace CrmClient.QueryConvert
{
    internal abstract class QueryConvertorBase<T> : IQueryConvertor<T>
    {
        public PropertiesMap PropertiesMap { get; private set; }
        public string EntityName { get; private set; }

        protected Type Type { get; private set; }
        protected bool TypeHasParameterlessConstructor { get; private set; }
        protected ConstructorInfo TypeConstructor { get; private set; }

        protected QueryConvertorBase(PropertiesMap propertiesMap, string entityName)
        {
            PropertiesMap = propertiesMap;
            Type = typeof(T);
            TypeHasParameterlessConstructor = Type.GetConstructor(new Type[] { }) != null;
            if (!TypeHasParameterlessConstructor)
            {
                var constructorParametersTypes = PropertiesMap.Select(i => i.Type).ToArray();
                TypeConstructor = Type.GetConstructor(constructorParametersTypes);
                if (TypeConstructor == null)
                {
                    var builder = new StringBuilder();
                    foreach (var constructorParameterType in constructorParametersTypes)
                        builder.Append(constructorParameterType.Name + ", ");
                    var constructorParametersTypesString = builder.Length > 0 ? builder.ToString(0, builder.Length - 2) : string.Empty;
                    throw new InvalidOperationException(string.Format("В типе '{0}' не найден конструктор с входными параметрами типов: {1}", Type.Name, constructorParametersTypesString));
                }
            }
            EntityName = entityName;
        }

        public T CreateItem(Entity entity)
        {
            if (TypeHasParameterlessConstructor)
                return CreateItemAndFill(entity);
            return CreateItemWithConstructor(entity);
        }

        public abstract Entity CreateEntity(T item, Guid? id);

        protected abstract T CreateItemWithConstructor(Entity entity);

        protected abstract T CreateItemAndFill(Entity entity);
    }
}
